import 'package:homepad/iot/basic_types.dart';
import 'package:homepad/iot/basic_node.dart';
import 'package:homepad/iot/message_def.dart';

class AirConditioner extends BasicNode {
  AirConditioner.fromJson(super.json) : super.fromJson();

  AirConditionerSystemMode systemMode = AirConditionerSystemMode.off;

  double localTemperature = 25;
  double coolingSetPoint = 25;
  double heatingSetPoint = 25;

  @override
  bool onAttributeReport(AttributePathIB path, dynamic data) {
    if (path.cluster != ClusterIds.thermostat) {
      return super.onAttributeReport(path, data);
    }

    if (path.attribute == ThermostatAttributeIds.localTemperature) {
      final newValue = (data as int) / 100;
      if (newValue == localTemperature) {
        return false;
      }
      localTemperature = newValue;
      return true;
    } else if (path.attribute == ThermostatAttributeIds.systemMode) {
      final newValue = AirConditionerSystemMode.byValue(data as int);
      if (newValue == null || newValue == systemMode) {
        return false;
      }
      systemMode = newValue;
      return true;
    } else if (path.attribute == ThermostatAttributeIds.coolingSetPoint) {
      final newValue = (data as int) / 100;
      if (newValue == coolingSetPoint) {
        return false;
      }
      coolingSetPoint = newValue;
      return true;
    } else if (path.attribute == ThermostatAttributeIds.heatingSetPoint) {
      final newValue = (data as int) / 100;
      if (newValue == heatingSetPoint) {
        return false;
      }
      heatingSetPoint = newValue;
      return true;
    }
    return false;
  }

  void setSystemMode(AirConditionerSystemMode mode) {
    systemMode = mode;
    delegate.onStateChanged("ep:$endpointId-mode:$systemMode");

    delegate.onAttributeSet(
        AttributePathIB(
            endpoint: endpointId,
            cluster: ClusterIds.thermostat,
            attribute: ThermostatAttributeIds.systemMode
        ), mode.value);
  }

  void setTargetTemperature(double target) {
    switch (systemMode) {
      case AirConditionerSystemMode.cool || AirConditionerSystemMode.dry:
        coolingSetPoint = target;
      case AirConditionerSystemMode.heat:
        heatingSetPoint = target;
      case AirConditionerSystemMode.auto:
        heatingSetPoint = target;
        coolingSetPoint = target;
      default:
        return;
    }
    delegate.onStateChanged("ep:$endpointId-target:$target");

    delegate.onAttributeSet(
        AttributePathIB(
            endpoint: endpointId,
            cluster: ClusterIds.thermostat,
            attribute: ThermostatAttributeIds.coolingSetPoint
        ), (target * 100).toInt());
  }

  double get targetTemperature {
    return switch (systemMode) {
      AirConditionerSystemMode.auto => coolingSetPoint,
      AirConditionerSystemMode.cool => coolingSetPoint,
      AirConditionerSystemMode.dry => coolingSetPoint,
      AirConditionerSystemMode.heat => heatingSetPoint,
      _ => localTemperature,
    };
  }

  @override
  BasicNodeState get state {
    if (!reachable) {
      return super.state;
    }
    return systemMode == AirConditionerSystemMode.off
        ? BasicNodeState.normal
        : BasicNodeState.activated;
  }

  @override
  void readAllState() {
    readAttribute(ClusterIds.thermostat, AttributeIds.empty);
  }

  @override
  String get desc {
    if (!reachable) {
      return super.desc;
    }
    switch (systemMode) {
      case AirConditionerSystemMode.cool || AirConditionerSystemMode.dry:
        return "${systemMode.name} $coolingSetPoint°";
      case AirConditionerSystemMode.heat:
        return "${systemMode.name} $heatingSetPoint°";
      case AirConditionerSystemMode.auto:
        if (localTemperature > targetTemperature) {
          return "${systemMode.name} $coolingSetPoint°";
        } else {
          return "${systemMode.name} $heatingSetPoint°";
        }
      default:
        return systemMode.name;
    }
  }
}
